using B.S.NewMedical.Api.Write.Application.Command.Doctor;
using B.S.NewMedical.Domain.Appointment;
using B.S.NewMedical.ErrorCode;
using B.S.NewMedical.Infrastructure;
using B.S.NewMedical.Infrastructure.Interface;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace B.S.NewMedical.Api.Write.Application.Handler.Doctor
{
    /// <summary>
    /// 开处方处理器
    /// </summary>
    public class AddPrescriptionHandler : IRequestHandler<AddPrescriptionCommand, ApiResult<int>>
    {
        private readonly IBaseRepository<Visit> _visitRepository;
        private readonly IBaseRepository<Prescription> _prescriptionRepository;
        private readonly IBaseRepository<PrescriptionItem> _prescriptionItemRepository;
        private readonly MyDbcontext _dbContext;
        private readonly ILogger<AddPrescriptionHandler> _logger;

        public AddPrescriptionHandler(
            IBaseRepository<Visit> visitRepository,
            IBaseRepository<Prescription> prescriptionRepository,
            IBaseRepository<PrescriptionItem> prescriptionItemRepository,
            MyDbcontext dbContext,
            ILogger<AddPrescriptionHandler> logger)
        {
            _visitRepository = visitRepository;
            _prescriptionRepository = prescriptionRepository;
            _prescriptionItemRepository = prescriptionItemRepository;
            _dbContext = dbContext;
            _logger = logger;
        }

        public async Task<ApiResult<int>> Handle(AddPrescriptionCommand request, CancellationToken cancellationToken)
        {
            using var transaction = await _dbContext.Database.BeginTransactionAsync(cancellationToken);
            try
            {
                _logger.LogInformation("开始处理开处方，就诊ID: {VisitId}", request.VisitId);

                // 参数验证
                if (request.VisitId <= 0)
                    return new ApiResult<int> { Code = ApiEnum.Fail, Msg = "就诊ID不能为空" };

                if (string.IsNullOrWhiteSpace(request.Type))
                    return new ApiResult<int> { Code = ApiEnum.Fail, Msg = "处方类型不能为空" };

                if (request.Items == null || !request.Items.Any())
                    return new ApiResult<int> { Code = ApiEnum.Fail, Msg = "处方明细不能为空" };

                // 检查就诊记录是否存在
                var visit = await _visitRepository.GetAll()
                    .FirstOrDefaultAsync(v => v.Id == request.VisitId && !v.IsDeleted, cancellationToken);

                if (visit == null)
                    return new ApiResult<int> { Code = ApiEnum.Fail, Msg = "就诊记录不存在" };

                // 生成处方号（时间戳+随机数）
                var prescriptionNo = $"CF{DateTime.Now:yyyyMMddHHmmss}{new Random().Next(1000, 9999)}";

                // 创建处方主表
                var prescription = new Prescription
                {
                    visit_id = request.VisitId,
                    prescription_no = prescriptionNo,
                    type = request.Type,
                    status = "待收费",
                    create_time = DateTime.Now,
                    IsDeleted = false
                };

                await _prescriptionRepository.CreateAsync(prescription);
                await _dbContext.SaveChangesAsync(cancellationToken); // 先保存以获取ID

                // 创建处方明细
                foreach (var item in request.Items)
                {
                    var prescriptionItem = new PrescriptionItem
                    {
                        Prescription_id = prescription.Id,
                        Drug_code = item.DrugCode,
                        Drug_name = item.DrugName,
                        Spec = item.Spec,
                        Qty = item.Qty,
                        Unit = item.Unit,
                        Days = item.Days,
                        Price = item.Price,
                        Amount = item.Amount,
                        IsDeleted = false
                    };

                    await _prescriptionItemRepository.CreateAsync(prescriptionItem);
                }

                await _dbContext.SaveChangesAsync(cancellationToken);
                await transaction.CommitAsync(cancellationToken);

                _logger.LogInformation("开处方成功，处方ID: {PrescriptionId}，处方号: {PrescriptionNo}", 
                    prescription.Id, prescriptionNo);

                return new ApiResult<int>
                {
                    Code = ApiEnum.Success,
                    Msg = "开处方成功",
                    Data = prescription.Id
                };
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync(cancellationToken);
                _logger.LogError(ex, "开处方时发生错误，就诊ID: {VisitId}", request.VisitId);
                return new ApiResult<int>
                {
                    Code = ApiEnum.Fail,
                    Msg = "开处方失败"
                };
            }
        }
    }
} 